import type { Ref } from 'vue';
import { ref, onMounted, onBeforeUnmount } from 'vue';

/** 默认配置 */
const DEFAULT_CONFIG = {
  /** 防御（默认关闭，简化逻辑） */
  defense: false,
  /** 文本颜色 */
  color: '#c0c4cc',
  /** 文本透明度 */
  opacity: 0.5,
  /** 文本字体大小 */
  size: 16,
  /** 文本字体 */
  family: 'serif',
  /** 文本倾斜角度 */
  angle: -20,
  /** 一处水印所占宽度（数值越大水印密度越低） */
  width: 300,
  /** 一处水印所占高度（数值越大水印密度越低） */
  height: 250,
  /** 默认水印文本 */
  text: 'API Hub',
};

type DefaultConfig = typeof DEFAULT_CONFIG;

interface Observer {
  parentElResizeObserver?: ResizeObserver | undefined;
}

/** body 元素 */
const bodyEl = ref<HTMLElement>(document.body);

/**
 * @name 水印 Composable
 * @description 1. 可以选择传入挂载水印的容器元素，默认是 body
 * @description 2. 简化版本，默认生效，无复杂防御机制
 */
export function useWatermark(parentEl: Ref<HTMLElement | null> = bodyEl) {
  // 备份文本
  let backupText: string | string[];

  // 最终配置
  let mergeConfig: DefaultConfig;

  // 水印元素
  let watermarkEl: HTMLElement | null = null;

  // 观察器
  const observer: Observer = {};

  // 设置水印
  const setWatermark = (
    text?: string | string[],
    config: Partial<DefaultConfig> = {}
  ) => {
    if (!parentEl.value)
      return console.warn(
        '请在 DOM 挂载完成后再调用 setWatermark 方法设置水印'
      );
    // 备份文本，使用传入的文本或默认文本
    backupText = text || DEFAULT_CONFIG.text;
    // 合并配置
    mergeConfig = { ...DEFAULT_CONFIG, ...config };
    // 创建或更新水印元素
    watermarkEl ? updateWatermarkEl() : createWatermarkEl();
    // 只监听容器元素的大小变化
    addElListener(parentEl.value);
  };

  // 创建水印元素
  const createWatermarkEl = () => {
    const isBody =
      parentEl.value!.tagName.toLowerCase() ===
      bodyEl.value.tagName.toLowerCase();
    const watermarkElPosition = isBody ? 'fixed' : 'absolute';
    const parentElPosition = isBody ? '' : 'relative';
    watermarkEl = document.createElement('div');
    watermarkEl.style.pointerEvents = 'none';
    watermarkEl.style.top = '0';
    watermarkEl.style.left = '0';
    watermarkEl.style.position = watermarkElPosition;
    watermarkEl.style.zIndex = '99999';
    const { clientWidth, clientHeight } = parentEl.value!;
    updateWatermarkEl({ width: clientWidth, height: clientHeight });
    // 设置水印容器为相对定位
    parentEl.value!.style.position = parentElPosition;
    // 将水印元素添加到水印容器中
    parentEl.value!.appendChild(watermarkEl);
  };

  // 更新水印元素
  const updateWatermarkEl = (
    options: Partial<{
      width: number;
      height: number;
    }> = {}
  ) => {
    if (!watermarkEl) return;
    backupText &&
      (watermarkEl.style.background = `url(${createBase64()}) left top repeat`);
    options.width && (watermarkEl.style.width = `${options.width}px`);
    options.height && (watermarkEl.style.height = `${options.height}px`);
  };

  // 创建 base64 图片
  const createBase64 = () => {
    const { color, opacity, size, family, angle, width, height } = mergeConfig;
    const canvasEl = document.createElement('canvas');
    canvasEl.width = width;
    canvasEl.height = height;
    const ctx = canvasEl.getContext('2d');
    if (ctx) {
      ctx.fillStyle = color;
      ctx.globalAlpha = opacity;
      ctx.font = `${size}px ${family}`;
      ctx.rotate((Math.PI / 180) * angle);

      // 支持多行文本
      if (Array.isArray(backupText)) {
        const lineHeight = size + 5; // 行高
        const startY = height / 2 - ((backupText.length - 1) * lineHeight) / 2;
        backupText.forEach((line, index) => {
          ctx.fillText(line, 0, startY + index * lineHeight);
        });
      } else {
        ctx.fillText(backupText, 0, height / 2);
      }
    }
    return canvasEl.toDataURL();
  };

  // 清除水印
  const clearWatermark = () => {
    if (!parentEl.value || !watermarkEl) return;
    // 移除对容器元素的监听
    removeListener();
    // 移除水印元素
    try {
      parentEl.value.removeChild(watermarkEl);
    } catch {
      console.warn('水印元素已不存在');
    } finally {
      watermarkEl = null;
    }
  };

  // 监听容器元素的大小变化
  const addElListener = (targetNode: HTMLElement) => {
    // 防止重复添加监听
    if (!observer.parentElResizeObserver) {
      // 监听 DOM 大小变化
      addResizeListener(targetNode);
    }
  };

  // 移除对容器元素的监听
  const removeListener = () => {
    // 移除 resize 监听
    observer.parentElResizeObserver?.disconnect();
    delete observer.parentElResizeObserver;
  };

  // 监听 DOM 大小变化
  const addResizeListener = (targetNode: HTMLElement) => {
    // 当 targetNode 元素大小变化时去更新整个水印的大小
    const resizeCallback = () => {
      const { clientWidth, clientHeight } = targetNode;
      updateWatermarkEl({ width: clientWidth, height: clientHeight });
    };
    // 创建一个观察器实例并传入回调
    observer.parentElResizeObserver = new ResizeObserver(resizeCallback);
    // 开始观察目标节点
    observer.parentElResizeObserver.observe(targetNode);
  };

  // 自动初始化水印
  onMounted(() => {
    // 延迟一点时间确保 DOM 完全渲染
    setTimeout(() => {
      setWatermark();
    }, 100);
  });

  // 在组件卸载前移除水印以及各种监听
  onBeforeUnmount(() => {
    clearWatermark();
  });

  return { setWatermark, clearWatermark };
}
